import { Component, Vue } from 'vue-property-decorator'
import './ChessBoard.scss'
import { ChessList, History } from './intenface'
import { _chessList, _boxList, _chessRelated, _chessBoard, initChessBoard } from './init'
import Worker from 'worker-loader!./worker'
import { myWebSocket } from './websocket'

let worker: Worker
const WIDTH = 66
const HEIGHT = 67

let isEnd = true
let historyStack: History[] = []
let isPlayWithComputer = true
let chooseID = ''
/** 1-表示先手 2-表示后手 */
let chessCharacter = 2
/** 是否是你的回合 */
let isYourTurn: boolean
/** 是否ai正在运算 */
let isAIComputed: boolean = false

let websocket: myWebSocket

@Component({
  template: require('./ChessBoard.html')
})

export default class ChessBoard extends Vue {
  // vue的模板渲染函数是在微任务队列中的，数据变化会立即执行setter，但不会立即更新视图
  // vue的 watch 函数也是在微任务队列中更新的
  chessList: ChessList = _chessList
  boxList: ChessList = _boxList
  isRedCamp = true
  roomNum: number = 0
  msgShow = ''
  msgSend = ''
  talkArea = ''
  onmessageFn = function (this: myWebSocket, event: MessageEvent) { }

  // 当访问该数据就立即执行此方法
  get boxID1() {
    return this.isRedCamp ? 'r_box1' : 'b_box1'
  }

  get boxID2() {
    return this.isRedCamp ? 'r_box2' : 'b_box2'
  }

  get opponentBoxID1() {
    return this.isRedCamp ? 'b_box1' : 'r_box1'
  }

  get opponentBoxID2() {
    return this.isRedCamp ? 'b_box2' : 'r_box2'
  }

  get distanceX() {
    return (x: number) => x * HEIGHT + 'px'
  }

  get distanceY() {
    return (y: number) => y * WIDTH + 'px'
  }


  created() {
    let that = this
    this.onmessageFn = function (this: myWebSocket, event: MessageEvent) {
      console.log("Received Message: " + event.data)
      isAIComputed = false
      let res = JSON.parse(event.data)
      that.msgShow = res.msg
      if (res.player == true) {
        chessCharacter = 1
      } else {
        chessCharacter = 2
      }
      if (res.canStart && !res.opponentQuit) {
        if (res.canOpponentRegret != 0) { //对方发来悔棋请求或同意
          switch (res.canOpponentRegret) {
            case 1:
              that.$confirm('你同意对方悔棋吗？', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'info'
              }).then(() => {
                this.message.canOpponentRegret = 2
                this.message.key = ``
                this.message.talk = ``
                this.sendMessage()
                that._regret()
              }).catch(() => {
                this.message.key = ``;
                this.message.talk = ``;
                this.message.canOpponentRegret = 3;
                that.msgShow = '悔棋肯定是拒绝的啦~'
                this.sendMessage();
              })
              break
            case 2:
              that._regret()
              that.msgShow = `你撞大运了，对方同意悔棋！`
              break
            case 3:
              that.msgShow = `很遗憾，对方不同意悔棋！`
              break
          }
          res.canOpponentRegret = 0
        } else if (res.talk) {
          that.talkArea += `对手：${res.talk}\n`
          res.talk = ``
        } else if (res.key == '') {
          if (chessCharacter == 1) {
            isYourTurn = true
          } else {
            isYourTurn = false
          }
          initChessBoard(chessCharacter, that.chessList, _chessBoard)
        } else if (res.key == 'restart') {
          that.$confirm('你同意对方请求重开一盘吗?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'info'
          }).then(() => {
            initChessBoard(chessCharacter, that.chessList, _chessBoard)
            this.message.key = `restartAgree`
            this.sendMessage();
          })
        } else if (res.key == 'restartAgree') {
          that.$message({
            type: 'success',
            message: `对手同意开始新的一局，对战愉快～`
          })
          initChessBoard(chessCharacter, that.chessList, _chessBoard)
        }

        // 移动棋子
        if (res.key && res.key != 'restart') {
          that.chessMove(res.key, Math.abs(9 - res.x), Math.abs(8 - res.y))
        }

      }
      this.message = res
    }
  }

  onSelectChess(e: any) {
    if (!isYourTurn) return
    if (isEnd) return
    const id = e.target.id
    let x, y
    if (id == 'chessboard') {
      y = Math.floor(e.offsetX / WIDTH)
      x = Math.floor(e.offsetY / HEIGHT)
    } else {
      y = Math.round(e.target.offsetLeft / WIDTH)
      x = Math.round(e.target.offsetTop / HEIGHT)
    }
    console.log('位置信息', id, x, y)

    // 设置选中状态
    if (id != 'chessboard' && this.isRedCamp == this.chessList[id].isRed) {
      if (id != 'chessboard' && _chessRelated.canChessOperation(id, chessCharacter)) {
        this.boxList[this.boxID1].x = x
        this.boxList[this.boxID1].y = y
        this.boxList[this.boxID1].display = 'block'
        chooseID = id
      }
    } else if (id != chooseID && chooseID) { // 棋子移动
      const checkCanMove = _chessRelated.checkCanMove(_chessRelated.getAllMovePosition(this.isRedCamp, this.chessList, chooseID, chessCharacter), x, y)

      if (!checkCanMove) {
        console.log('走法不符规则，不能移动')
        return
      }
      this.chessMove(chooseID, x, y)
      // ai走棋
      if (isPlayWithComputer) {
        isAIComputed = true
        worker.postMessage({ _chessBoard, chessList: this.chessList, isAIfirst: chessCharacter == 2 ? true : false })
      } else { // 双人对战传递消息
        websocket.message.key = chooseID;
        websocket.message.x = x;
        websocket.message.y = y;
        websocket.sendMessage()
      }
    }
  }

  /**
   * @description 更新棋盘上的棋子信息
   * */
  updateChessBoard(id: string, x: number, y: number) {
    _chessBoard[x][y] = id
    _chessBoard[this.chessList[id].x][this.chessList[id].y] = ''
  }

  chessMove(id: string, x: number, y: number) {
    if (!id) {
      console.error(`id不合法：${id}`)
      return
    }

    // 原地要留下标记
    this.boxList[this.boxID2].x = this.chessList[id].x
    this.boxList[this.boxID2].y = this.chessList[id].y
    this.boxList[this.boxID2].display = 'block'

    const chessKilled = _chessBoard[x][y]

    // 记录历史，用于悔棋
    let history: History = {
      moveID: id
    }
    // 杀子
    if (chessKilled) {
      history.killID = chessKilled
      this.chessList[chessKilled].display = 'none'
    }

    historyStack.push(history)

    this.chessList[id]?.history?.push({
      x: this.chessList[id].x,
      y: this.chessList[id].y,
    })

    // 落子的标记
    this.boxList[this.boxID1].x = x
    this.boxList[this.boxID1].y = y
    this.boxList[this.boxID1].display = 'block'

    console.log(`${id}:(${this.chessList[id].x},${this.chessList[id].y})移动到(${x},${y})`)

    // 更新位置
    this.updateChessBoard(id, x, y)
    this.chessList[id].x = x
    this.chessList[id].y = y

    // 落子后清除对手的标记
    this.boxList[this.opponentBoxID1].display = 'none'
    this.boxList[this.opponentBoxID2].display = 'none'

    if (chessKilled == 'j1') {
      this.$message({
        type: 'success',
        showClose: true,
        message: '黑棋胜！'
      });
      isEnd = true
      return
    }
    if (chessKilled == 'J1') {
      this.$message({
        type: 'success',
        showClose: true,
        message: '红棋胜！'
      });
      isEnd = true
      return
    }

    isYourTurn = !isYourTurn
    this.isRedCamp = !this.isRedCamp
    console.log('===============棋手回合轮换==================')
  }

  onPlayWithComputer() {
    if (isAIComputed) {
      this.$message({
        type: 'info',
        showClose: true,
        message: '请等待电脑走子后进行该操作'
      })
      return
    }

    if (isEnd) {
      this.$confirm('是否重新开始新的一局?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'info'
      }).then(() => {
        initChessBoard(chessCharacter, this.chessList, _chessBoard)
        isEnd = false
        // 电脑先手的话,ai走棋
        if (chessCharacter == 2) {
          isYourTurn = false
          isAIComputed = true
          worker.postMessage({ _chessBoard, chessList: this.chessList, isAIfirst: true })
        } else {
          isYourTurn = true
        }
      })
    }
    isPlayWithComputer = true
    if (!worker) {
      worker = new Worker()
      worker.onmessage = (e: { data: any }) => {
        const result = e.data
        console.log('AI search result============', result)
        if (!result) {
          let msg
          if (chessCharacter == 1) {
            msg = '绝杀，红棋胜'
          } else {
            msg = '绝杀，黑棋胜'
          }
          this.$message({
            type: 'success',
            showClose: true,
            message: msg
          });
          isEnd = true
          return
        }
        this.chessMove(result.key, result.x, result.y)
      }
      worker.addEventListener('error', console.error)
    }
  }

  onStartOnline() {
    isPlayWithComputer = false
    if (!websocket) {
      websocket = new myWebSocket(this.onmessageFn)
    }
    this.$prompt('请输入房间号', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      inputPattern: /\d+/,
      inputErrorMessage: '房间号必须是数字'
    }).then((msg: any) => {
      this.roomNum = Number(msg.value)
      websocket.message.roomID = Number(msg.value)
      websocket.sendMessage()
      this.$message({
        type: 'success',
        message: `进入${msg.value}号房...`
      })
    })
  }

  _regret() {

    let history: History = historyStack.pop()!
    let moveID = history.moveID

    let chessToRegret = this.chessList[moveID]
    let preChess = chessToRegret.history?.pop()!

    this.isRedCamp = !this.isRedCamp
    isYourTurn = !isYourTurn

    this.updateChessBoard(moveID, preChess.x, preChess.y)
    // 棋子回到原来位置
    this.chessList[moveID].x = preChess.x
    this.chessList[moveID].y = preChess.y

    // 显示被杀的棋子
    if (history.killID) {
      let chessToKill = this.chessList[history.killID]
      chessToKill.display = 'block'
      _chessBoard[chessToKill.x][chessToKill.y] = history.killID
      console.log(history.killID, chessToKill.x, chessToKill.y)
    }

    // 恢复落子的标记
    if (historyStack.length > 0) {
      let boxHistory: History = historyStack[historyStack.length - 1]
      let currentBox = this.chessList[boxHistory.moveID]
      let preBox = currentBox.history![currentBox.history!.length - 1]
      this.boxList[this.opponentBoxID1].x = currentBox.x
      this.boxList[this.opponentBoxID1].y = currentBox.y
      this.boxList[this.opponentBoxID1].display = 'block'

      this.boxList[this.opponentBoxID2].x = preBox.x
      this.boxList[this.opponentBoxID2].y = preBox.y
      this.boxList[this.opponentBoxID2].display = 'block'

      this.boxList[this.boxID1].display = 'none'
      this.boxList[this.boxID2].display = 'none'
    } else {
      this.boxList[this.boxID1].display = 'none'
      this.boxList[this.boxID2].display = 'none'
      this.boxList[this.opponentBoxID1].display = 'none'
      this.boxList[this.opponentBoxID2].display = 'none'
    }

  }

  onRegret() {
    console.log('===============请求悔棋==================')
    if (isAIComputed && isPlayWithComputer) {
      this.$message({
        type: 'info',
        showClose: true,
        message: '请等待电脑走子后进行该操作'
      })
      return
    }

    if (isYourTurn && !isPlayWithComputer) {
      this.$message({
        type: 'info',
        showClose: true,
        message: '亲，只有在你对手的回合才能悔棋哦!'
      })
      return
    }

    if (historyStack.length == 0) {
      this.$message({
        type: 'info',
        showClose: true,
        message: '还没走呢，悔啥子棋哦...'
      })
      return
    }

    this.$confirm('哎呀，走错了? 是否悔棋?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'info'
    }).then(() => {
      if (isPlayWithComputer) {
        this._regret()
        this._regret()
        this.$message({
          type: 'success',
          showClose: true,
          message: '悔棋成功! 下次认真点...嗯'
        });
      } else {
        websocket.message.canOpponentRegret = 1;
        websocket.message.key = ``;
        websocket.message.talk = ``;
        websocket.sendMessage();
        this.msgShow = '等待对手同意...'
      }
    }).catch(() => {
      this.$message({
        type: 'info',
        showClose: true,
        message: '悔棋是不可能悔棋的...'
      });
    });
  }

  onSendMsg() {
    websocket.message.talk = this.msgSend
    websocket.message.key = ``
    websocket.sendMessage()
    this.talkArea = `${this.talkArea}我：${this.msgSend}\n`
  }
}
